package com.nlx.notes.module.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.nlx.notes.module.bean.bo.CategoryMonthStatisticsBo;
import com.nlx.notes.module.bean.bo.FlowMonthAmountStatisticsBO;
import com.nlx.notes.module.bean.bo.TransactionsBO;
import com.nlx.notes.module.bean.dto.FlowPageQueryDTO;
import com.nlx.notes.module.bean.dto.FlowSaveDTO;
import com.nlx.notes.module.bean.dto.TransactionsQueryDTO;
import com.nlx.notes.module.bean.dto.flow.FlowChangeDTO;
import com.nlx.notes.module.bean.dto.statistics.TopStatisticsDBQueryDTO;
import com.nlx.notes.module.bean.vo.flow.FlowStatisticsSumVO;
import com.nlx.notes.module.core.generator.IdGenerator;
import com.nlx.notes.module.core.util.AmountConverterUtils;
import com.nlx.notes.module.core.util.DataConvertorUtils;
import com.nlx.notes.module.core.util.DateUtils;
import com.nlx.notes.module.core.util.JSONUtils;
import com.nlx.notes.module.entity.Transactions;
import com.nlx.notes.module.helper.flow.FlowEventHelper;
import com.nlx.notes.module.mapper.TransactionsMapper;
import com.nlx.notes.module.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.*;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author nlx
 * @since 2024-12-15
 */

@Slf4j
@Service
@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class TransactionsServiceImpl extends ServiceImpl<TransactionsMapper, Transactions> implements ITransactionsService {

    final IFlowDayStatisticsService flowDayStatisticsService;

    final IFlowMonthStatisticsService flowMonthStatisticsService;

    final IFlowYearStatisticsService flowYearStatisticsService;

    final IAccountsService accountsService;

    final ICategoriesService categoriesService;

    final FlowEventHelper flowEventHelper;

    final IAccountBooksService  accountBooksService;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long saveFlow(FlowSaveDTO flowSaveDTO) {
        Transactions transactions = DataConvertorUtils.copyProperties(flowSaveDTO, Transactions::new);
        transactions.setFlowId(IdGenerator.generateOrderId());
        transactions.setAmount(AmountConverterUtils.convertYuanToFen(flowSaveDTO.getAmount()));
        transactions.setTransactionDate(DateUtils.formatDate(flowSaveDTO.getTransactionDate()));
        transactions.setAccountId(flowSaveDTO.getAccountId());
        transactions.setDelFlag(0);
        transactions.setBookId(accountBooksService.getCurrentBook(flowSaveDTO.getUserId()).getId());
        //获取一级分类id
        transactions.setCategoryId(categoriesService.findParentIdByCategoryId(flowSaveDTO.getCategoryId()));
        transactions.setSecondCategoryId(flowSaveDTO.getCategoryId());
        this.save(transactions);
        FlowChangeDTO flowChangeDTO = new FlowChangeDTO();
        flowChangeDTO.setFlowId(transactions.getId());
        flowChangeDTO.setFlowNewDate(flowSaveDTO.getTransactionDate());
        flowChangeDTO.setUserId(flowSaveDTO.getUserId());
        flowChangeDTO.setTransactionType(flowSaveDTO.getTransactionType());
        flowChangeDTO.setBookId(transactions.getBookId());
        flowEventHelper.flowChange(flowChangeDTO);
        return transactions.getId();
    }


    @Override
    public void initData(Long userId){
        TransactionsQueryDTO transactionsQueryDTO = new TransactionsQueryDTO();
        transactionsQueryDTO.setUserId(userId);
        List<Transactions> list = this.findListByCondition(transactionsQueryDTO);
        log.info("数据大小：{}",list.size());
        for (Transactions transactions : list){
            log.info("刷新数据：{}",JSONUtils.toString(transactions));
            FlowChangeDTO flowChangeDTO = new FlowChangeDTO();
            flowChangeDTO.setFlowId(transactions.getId());
            flowChangeDTO.setFlowNewDate(DateUtils.parseDate(transactions.getTransactionDate()));
            flowChangeDTO.setUserId(transactions.getUserId());
            flowChangeDTO.setTransactionType(transactions.getTransactionType());
            flowEventHelper.flowChange(flowChangeDTO);
        }
    }


    @Override
    public List<Transactions> pageByCondition(FlowPageQueryDTO flowPageQueryDTO) {
        flowPageQueryDTO.setPage( (flowPageQueryDTO.getPage() -1) * flowPageQueryDTO.getPageSize() );
        return this.getBaseMapper().pageByCondition(flowPageQueryDTO);
    }

    @Override
    public long countByCondition(FlowPageQueryDTO flowPageQueryDTO) {
        return this.getBaseMapper().countByCondition(flowPageQueryDTO);
    }

    @Override
    public Transactions findByCondition(TransactionsQueryDTO transactionsQueryDTO) {
        if(null == transactionsQueryDTO.getUserId()){
            return null;
        }
        return this.getOne(Wrappers.lambdaQuery(Transactions.class)
                .eq(null !=transactionsQueryDTO.getId(), Transactions::getId,transactionsQueryDTO.getId())
                .eq(null != transactionsQueryDTO.getUserId(),Transactions::getUserId,transactionsQueryDTO.getUserId())
                .eq(Transactions::getDelFlag,0)
                .last(" limit 1"));
    }

    @Override
    public void removeFlow(Long id) {
        if(null == id){
            return ;
        }
        this.update(Wrappers.lambdaUpdate(Transactions.class)
                .set(Transactions::getDelFlag,1)
                .eq(Transactions::getId,id));
    }


    @Override
    public int findIncomeAmountByCondition(FlowPageQueryDTO flowPageQueryDTO) {
        return this.getBaseMapper().findAmountByCondition(flowPageQueryDTO);
    }

    @Override
    public FlowStatisticsSumVO sumByDay(LocalDate flowDate, Long userId) {
        return this.getBaseMapper().sumByDay(flowDate,userId);
    }

    @Override
    public List<CategoryMonthStatisticsBo> findCategoryStatistics(String startDate, String endDate, Long userId,Long bookId) {
        return this.getBaseMapper().findCategoryStatistics(startDate,endDate,userId,bookId);
    }

    @Override
    public FlowMonthAmountStatisticsBO sumByDate(String starDate, String endDate, Long userId,Long bookId) {

        return this.getBaseMapper().sumByDate(starDate,endDate,userId,bookId);
    }

    @Override
    public List<Transactions> findListByCondition(TransactionsQueryDTO transactionsQueryDTO) {
        log.info("查询 list通过条件，参数：{}", JSONUtils.toString(transactionsQueryDTO));
        return this.getBaseMapper().findListByCondition(transactionsQueryDTO);
    }

    @Override
    public List<TransactionsBO> findTop(TopStatisticsDBQueryDTO topStatisticsDBQueryDTO) {
        return this.getBaseMapper().findTop(topStatisticsDBQueryDTO);
    }
}